// 版权所有2010 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package math

// 原始C代码和下面的注释来自
// FreeBSD的/usr/src/lib/msun/src/e_余数。带着这个通知来到
// 。go代码是
// 原版C.
// 
// ============================================================================================================
// Sun Microsystems，Inc.版权所有。
// 
// 由Sun Microsystems，Inc.业务部门SunPro开发。
// 使用、复制、修改和分发本
// 软件的权限是免费授予的，前提是保留本通知
// 的权利。第19页
// 最接近x/y的整数（在一半的情况下，选择偶数）。
// 方法：
// 基于Mod（）精确返回x-[x/y]切碎的*y。

// 余数返回x/y的IEEE 754浮点余数。
// 
// 特殊情况是：
// 余数（±Inf，y）=NaN 
// 余数（NaN，y）=NaN 
// 余数（x，0）=NaN 
// 余数（x，±Inf）=x 
// 余数（x，NaN）=NaN 
func Remainder(x, y float64) float64 {
	if haveArchRemainder {
		return archRemainder(x, y)
	}
	return remainder(x, y)
}

func remainder(x, y float64) float64 {
	const (
		Tiny    = 4.45014771701440276618e-308 // 
		HalfMax = MaxFloat64 / 2
	)
	// 特殊情况
	switch {
	case IsNaN(x) || IsNaN(y) || IsInf(x, 0) || y == 0:
		return NaN()
	case IsInf(y, 0):
		return x
	}
	sign := false
	if x < 0 {
		x = -x
		sign = true
	}
	if y < 0 {
		y = -y
	}
	if x == y {
		if sign {
			zero := 0.0
			return -zero
		}
		return 0
	}
	if y <= HalfMax {
		x = Mod(x, y+y) // 现在x<2y 
	}
	if y < Tiny {
		if x+x > y {
			x -= y
			if x+x >= y {
				x -= y
			}
		}
	} else {
		yHalf := 0.5 * y
		if x > yHalf {
			x -= y
			if x >= yHalf {
				x -= y
			}
		}
	}
	if sign {
		x = -x
	}
	return x
}
